//自定义composition API
import { IGlobalState } from '@/store';
import { IHeaderInfo, IHomeState, IPostData, NAV_TYPES } from '@/typings';
import { computed, onMounted, Ref } from 'vue';
import { Store } from 'vuex';
import { headerInfos } from '../router';
import _ from 'lodash';

/**
 * 获取header对应的路由信息的方法
 * @param routeName watch监听的路由名称
 * @returns 路由信息里的某一项对象
 */
function useRouteInfo(routeName: string): IHeaderInfo | undefined {
  //遍历路由文件定义的数组headerInfos
  //返回相同名称的那一项数据对象
  const routeInfo: IHeaderInfo | undefined = headerInfos.find(
    (item: IHeaderInfo) => item.name === routeName
  );

  return routeInfo;
}

/**
 * 图片淡入:更改图片样式,加载时显示图片
 * @param imgRefs 一个数组 [imgRef1, imgRef2, imgRef3]
 */
function useImgShow(imgRefs: Ref<null | HTMLElement>[]): void {
  //收集Item里的所有图片ref,遍历refs，当图片加载完成的时候让图片透明度为1
  imgRefs.map((imgRef) => {
    const oImg = imgRef.value!;

    //图片加载时触发的事件
    oImg.onload = function () {
      oImg.style.opacity = '1';
    };
  });
}

/**
 * 滚动新闻列表页面到底部时触发加载更多
 * @param store 仓库操作store
 * @param module store里面的模块名称home
 * @param actionType 操作哪里的newsList 如SET_NEWS_LIST
 * @param element 绑定scroll事件的ref元素
 * @returns 返回一个对象包含最新的isLoading和hasMore的引用ref
 */
function useLoadingMore(
  store: Store<IGlobalState>,
  module: string,
  actionType: string,
  element: Ref<null | HTMLElement>
) {
  let el: HTMLElement;
  let state: IHomeState;

  //类型断言操作 通过模块名称的不同去断言类型
  switch (module) {
    case 'home':
      state = store.state.home as IHomeState;
      break;
    default:
      break;
  }

  //直到挂载后
  onMounted(() => {
    //拿到绑定ref的元素
    //注意: element.value有可能是null或HTMLElement,所有需要断言为HTMLElement
    el = element.value as HTMLElement;

    //绑定事件处理函数,并做防抖处理
    el.addEventListener('scroll', _.debounce(_loadMore, 300), false);

    //定义函数
    function _loadMore(): void {
      //浏览器可见区域高度(列表高度)
      const listHeight: number = el.clientHeight;
      //滚动高度(会超过视口)
      const scrollHeight: number = el.scrollHeight;
      //滚动的视口上边离页面的滚动距离
      const scrollTop: number = el.scrollTop;
      //拿到新闻类型
      const type: NAV_TYPES = computed(() => state.currentType).value;
      //拿到页码
      const pageNum: number = computed(() => state.newsList.pageNum).value;
      //拿到每页返回条数
      const count: number = computed(() => state.newsList.count).value;

      //触底时需要加载更多
      //当列表高度 + 滚动top值 >= 滚动高度 - 30 证明还有30像素就触底了
      if (listHeight + scrollTop >= scrollHeight - 30) {
        //操作state
        //只要距底部还有30像素,就继续请求数据,更新加载更多列表内容
        //module模块写法 home/SET_NEWS_LIST
        store.dispatch(`${module}/${actionType}`, <IPostData>{
          type,
          pageNum,
          count
        });
      }
    }
  });

  return {
    isLoading: computed(() => state.newsList.isLoading),
    hasMore: computed(() => state.newsList.hasMore)
  };
}

export { useRouteInfo, useImgShow, useLoadingMore };
